package com.mobimagic.lockscreen.activity;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;

import com.mobimagic.lockscreen.remaintime.CalcSlopeStrategy;
import com.mobimagic.lockscreen.remaintime.MobileChargingService;
import com.mobimagic.lockscreen.remaintime.aidl.ChargingData;
import com.mobimagic.lockscreen.remaintime.aidl.ChargingDatas;
import com.mobimagic.lockscreen.remaintime.aidl.ChargingServiceAidl;
import com.mobimagic.lockscreen.remaintime.aidl.RemaintTimeWatcher;
import com.mobimagic.lockscreen.util.ScreenUtil;

public class ChargingProgressActivity extends BaseActivity {

    ChargingView chargingView;
    Handler handler;

    private static final String TAG = "ChargingProgressActivity";
    private static final List<Integer> TIME_ZOOM = new ArrayList<Integer>();
    static {

        TIME_ZOOM.add(60);
        TIME_ZOOM.add(60 * 2);
        TIME_ZOOM.add(60 * 5);
        TIME_ZOOM.add(60 * 10);
        TIME_ZOOM.add(60 * 15);
        TIME_ZOOM.add(60 * 30);
        TIME_ZOOM.add(60 * 60);
        TIME_ZOOM.add(60 * 60 * 2);
        TIME_ZOOM.add(60 * 60 * 3);
        TIME_ZOOM.add(60 * 60 * 4);
        TIME_ZOOM.add(60 * 60 * 5);
        TIME_ZOOM.add(60 * 60 * 6);
        TIME_ZOOM.add(60 * 60 * 7);
        TIME_ZOOM.add(60 * 60 * 8);
        TIME_ZOOM.add(60 * 60 * 9);
        TIME_ZOOM.add(60 * 60 * 10);
        TIME_ZOOM.add(60 * 60 * 11);
        TIME_ZOOM.add(60 * 60 * 12);
        TIME_ZOOM.add(60 * 60 * 15);
        TIME_ZOOM.add(60 * 60 * 18);
        TIME_ZOOM.add(60 * 60 * 24);
    }
    ChargingDatas chargingDatas;
    private ServiceConnection serviceConnection;
    private ChargingServiceAidl chargingServiceAidl;
    private RemaintTimeWatcher remaintTimeWatcher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler = new Handler();
        chargingView = new ChargingView(this);
        chargingView.setBackgroundColor(Color.GRAY);
        FrameLayout frameLayout = new FrameLayout(this);
        frameLayout.addView(chargingView);
        Button start = new Button(this);
        start.setText("开");
        Button simple = new Button(this);
        simple.setText("简");
        Button avg = new Button(this);
        avg.setText("均");
        Button doubleSimple = new Button(this);
        doubleSimple.setText("二");
        Button duishu = new Button(this);
        duishu.setText("一二");

        start.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                chargingView.postInvalidate();
            }
        });
        simple.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                try {
                    chargingServiceAidl.calc(CalcSlopeStrategy.getSlopeStrategyIndex(CalcSlopeStrategy.Simple.class));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        avg.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                try {
                    chargingServiceAidl.calc(CalcSlopeStrategy.getSlopeStrategyIndex(CalcSlopeStrategy.Average.class));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        doubleSimple.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                try {
                    chargingServiceAidl.calc(CalcSlopeStrategy
                            .getSlopeStrategyIndex(CalcSlopeStrategy.DoubleSimple.class));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        duishu.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                try {
                    chargingServiceAidl.calc(CalcSlopeStrategy
                            .getSlopeStrategyIndex(CalcSlopeStrategy.Exponential.class));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

            }
        });

        Button add = new Button(this);
        add.setText("+");
        add.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                chargingView.addScale();

            }
        });
        Button reduce = new Button(this);
        reduce.setText("-");
        reduce.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                chargingView.reduceScale();
            }
        });

        Button auto = new Button(this);
        auto.setText("自");

        auto.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                chargingView.autoScale();
            }
        });
        LinearLayout linearLayout = new LinearLayout(this);
        LinearLayout linearLayout1 = new LinearLayout(this);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(-2, -2);
        layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
        frameLayout.addView(linearLayout, layoutParams);
        FrameLayout.LayoutParams layoutParams1 = new FrameLayout.LayoutParams(-2, -2);
        layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
        layoutParams1.topMargin = ScreenUtil.dpToPxInt(this, 50);
        frameLayout.addView(linearLayout1, layoutParams1);

        linearLayout.addView(start);
        linearLayout.addView(avg);
        linearLayout.addView(simple);
        linearLayout.addView(doubleSimple);
        linearLayout.addView(duishu);
        linearLayout1.addView(add);
        linearLayout1.addView(reduce);
        linearLayout1.addView(auto);
        setContentView(frameLayout);
        remaintTimeWatcher = new RemaintTimeWatcher.Stub() {

            @Override
            public void onRemaintTimeChanged(int remaind) throws RemoteException {
                if (DEBUG) {
                    Log.d(TAG, "收到剩余充电时间" + remaind);
                }
                chargingDatas = chargingServiceAidl.getChargingDatas();
                chargingView.invalidate();
            }
        };
        Intent chargingIntent = new Intent(this, MobileChargingService.class);
        serviceConnection = new ServiceConnection() {

            @Override
            public void onServiceDisconnected(ComponentName name) {
                chargingServiceAidl = null;
            }

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                chargingServiceAidl = ChargingServiceAidl.Stub.asInterface(service);
                try {
                    chargingServiceAidl.register(remaintTimeWatcher);
                    chargingDatas = chargingServiceAidl.getChargingDatas();
                    if (DEBUG) {
                        Log.d(TAG, "chargingDatas ");
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

            }
        };
        startService(chargingIntent);
        bindService(chargingIntent, serviceConnection, Context.BIND_AUTO_CREATE);

    }

    protected void onDestroy() {
        super.onDestroy();
        try {
            chargingServiceAidl.unRegister(remaintTimeWatcher);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        unbindService(serviceConnection);
    }

    private class ChargingView extends View {
        PathEffect effects = new DashPathEffect(new float[] { 1, 2, 4, 8 }, 1);
        private long x0, xMax;
        private float y0, yMax;
        Path path = new Path();
        Path xxPath = new Path();
        Paint paint = new Paint();
        private float xLength, yLength;
        private Path valuePath = new Path();
        private int gap;
        private List<PointF> points = new ArrayList<PointF>();
        private float radius;
        private Map<PointF, ChargingData> pointsMap = new HashMap<PointF, ChargingData>();
        private float coordinateLineWidth, lineWidth;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
        Date date = new Date();
        private boolean isAutoScale = true;
        private int currentScaleIndex = -1;
        private RectF scrollBarRect = new RectF();
        private int scrollBarHeight = 0;
        private int scrollBarMarginBottom = 0;
        int start;

        public ChargingView(Context context) {
            super(context);
            gap = ScreenUtil.dpToPxInt(context, 50);
            radius = ScreenUtil.dpToPxInt(context, 3);
            coordinateLineWidth = ScreenUtil.dpToPxInt(context, 2);
            lineWidth = ScreenUtil.dpToPxInt(context, 1);
            scrollBarHeight = ScreenUtil.dpToPxInt(context, 20);
            scrollBarMarginBottom = ScreenUtil.dpToPxInt(context, 20);

        }

        public void addScale() {
            currentScaleIndex--;
            isAutoScale = false;
            invalidate();
        }

        public void reduceScale() {
            isAutoScale = false;
            currentScaleIndex++;
            invalidate();
        }

        public void autoScale() {
            isAutoScale = true;
            invalidate();
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        }

        private int getY0() {
            return getMeasuredHeight() - gap;
        }

        private int getX0() {
            return gap;
        }

        private int getYMax() {
            return gap * 3;
        }

        private int getXMax() {
            return getMeasuredWidth() - gap;
        }

        private void gentratePath() {
            path.reset();
            points.clear();
            pointsMap.clear();
            path.moveTo(getX0(), getYMax());
            path.lineTo(getX0(), getY0());
            path.lineTo(getXMax(), getY0());
            ChargingDatas datas = chargingDatas;
            List<ChargingData> list = datas.getChargingDatas();
            if (list.size() == 0) {
                return;
            }
            valuePath.reset();
            xLength = getXMax() - getX0();
            yLength = getYMax() - getY0();

            float xD = xLength / (xMax - x0);
            float yD = yLength / (yMax - y0);
            for (int i = 0; i < list.size(); i++) {
                ChargingData chargingData = list.get(i);
                float y = 0;
                float x = 0;
                long time = chargingData.getTime();
                float battery = chargingData.getBattery();
                x = getX0() + time * xD;
                y = getY0() + battery * yD;
                PointF pointf = new PointF(x, y);
                points.add(pointf);
                pointsMap.put(pointf, chargingData);
                if (i == 0) {
                    valuePath.moveTo(x, y);
                } else {
                    valuePath.lineTo(x, y);
                }

            }

        }

        private void generateXYMax() {
            List<ChargingData> list = chargingDatas.getChargingDatas();
            if (list.size() == 0) {
                return;
            }
            yMax = chargingDatas.getScaleBattery();
            y0 = 0f;
            xMax = 0;
            x0 = 0;
            if (isAutoScale) {
                if (list.size() <= 1) {
                    xMax = x0 + 60;
                } else {
                    ChargingData last = list.get(list.size() - 1);
                    int time = last.getTime();
                    for (int i = 0; i < TIME_ZOOM.size(); i++) {
                        int timeZoom = TIME_ZOOM.get(i);
                        if (time <= timeZoom) {
                            xMax = timeZoom;
                            currentScaleIndex = i;
                            break;
                        }
                    }

                }
            } else {
                if (currentScaleIndex >= TIME_ZOOM.size()) {
                    currentScaleIndex = TIME_ZOOM.size() - 1;
                } else if (currentScaleIndex < 0) {
                    currentScaleIndex = 0;
                }
                xMax = TIME_ZOOM.get(currentScaleIndex);
            }
        }

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (chargingDatas == null) {
                return;
            }
            generateXYMax();
            gentratePath();
            paint.setColor(Color.BLACK);
            paint.setStyle(Style.STROKE);
            paint.setStrokeWidth(2);
            canvas.drawPath(path, paint);
            canvas.drawPath(valuePath, paint);
            paint.setTextAlign(Align.RIGHT);
            paint.setStyle(Style.FILL);
            paint.setTextSize(ScreenUtil.dpToPx(getContext(), 12));
            canvas.drawText(yMax + "", getX0(), getYMax(), paint);
            long xx = xMax - x0;
            String t = getTimeStr(xx);
            canvas.drawText(t, getXMax(), getY0() + ScreenUtil.dpToPx(getContext(), 12), paint);
            for (PointF pointF : points) {
                canvas.drawCircle(pointF.x, pointF.y, radius, paint);
            }

            long start = chargingDatas.startTime;
            if (chargingDatas.chargingDatas.size() > 0) {
                start = start + chargingDatas.chargingDatas.get(0).getTime() * 1000;
            }
            date.setTime(start);
            String text = simpleDateFormat.format(date);
            canvas.drawText(text, getX0(), getY0(), paint);

            if (needDrawLines) {
                PointF pointf = findPointf();
                if (pointf == null) {
                    return;
                }
                paint.setStyle(Style.STROKE);
                paint.setStrokeWidth(lineWidth);
                float x = pointf.x;
                float y = pointf.y;
                if (lastPointX > getXMax()) {
                    x = getXMax();
                } else if (lastPointX < getX0()) {
                    x = getX0();
                }
                paint.setColor(Color.BLACK);
                canvas.drawLine(x, getY0(), x, getYMax(), paint);
                canvas.drawLine(x, getY0(), x, getYMax(), paint);
                canvas.drawLine(getX0(), y, x, y, paint);
                paint.setColor(Color.RED);
                canvas.drawLine(getX0(), getYMax(), getXMax(), getYMax(), paint);
                paint.setColor(Color.BLACK);
                ChargingData chargingData = pointsMap.get(pointf);
                int reminderTime = chargingData.getRemainder();
                canvas.drawText(getTimeStr(reminderTime), x, getYMax(), paint);
                canvas.drawText(getTimeStr(chargingData.getTime()), x, getY0(), paint);
                canvas.drawText(chargingData.getBattery() + "", getX0(), y, paint);

                //画虚线
                int endTime = chargingData.getEndTime();
                int endBattery = chargingDatas.getScaleBattery();
                float endY = getYMax();
                float xD = xLength / (xMax - x0);
                float yD = yLength / (yMax - y0);
                float endX = getX0() + endTime * xD;
                float ds = (endY - y) / (endX - x);

                //                (endY-yyy)/(endX-getX0())=ds;
                float beginY = endY - ds * (endX - getX0());
                xxPath.reset();
                xxPath.moveTo(getX0(), beginY);
                xxPath.lineTo(x, y);
                xxPath.lineTo(endX, endY);
                xxPath.lineTo(endX, getY0());
                paint.setPathEffect(effects);
                canvas.drawPath(xxPath, paint);
                paint.setPathEffect(null);
                paint.setTextAlign(Align.LEFT);
                canvas.drawText(getTimeStr(endTime), endX, (getY0() + getYMax()) / 2, paint);

            }

        }

        private boolean touchScrollBar(float y) {
            return y < scrollBarRect.bottom;
        }

        private String getTimeStr(long xx) {
            //            xx = Math.abs(xx);
            String t = xx + "s";
            if (xx <= 60) {
            } else if (xx <= 60 * 60) {
                t = (xx + 59) / 60 + "分";
            } else {
                t = xx / (60 * 60) + "小时";
                t = t + (xx % (60 * 60) + 59) / 60 + "分";
            }
            if (xx < 0) {
                t = "-" + t;
            }
            return t;
        }

        private PointF findPointf() {
            float minAbslotex = Float.MAX_VALUE;
            int minIndex = -1;
            PointF touchPoint = null;
            for (int i = 0; i < points.size(); i++) {
                PointF pointF = points.get(i);
                float absloateX = Math.abs(pointF.x - lastPointX);
                if (minAbslotex > absloateX) {
                    minIndex = i;
                    minAbslotex = absloateX;
                }
            }
            if (minIndex > -1) {
                touchPoint = points.get(minIndex);
            }
            return touchPoint;
        }

        private boolean needDrawLines;
        private boolean touchScrollBar;
        private float lastPointX;
        private float lastPointY;

        @Override
        public boolean onTouchEvent(MotionEvent event) {
            lastPointX = event.getX();
            lastPointY = event.getY();

            switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:

                if (touchScrollBar(lastPointY)) {
                    touchScrollBar = true;
                } else {
                    needDrawLines = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                needDrawLines = false;
                touchScrollBar = false;
                break;

            default:
                break;
            }
            invalidate();

            return true;

        }
    }

}
